﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Wimm.Common.Entities;
using Wimm.Common.Interfaces.Services;
using Windows.UI.Xaml;

namespace Wimm.UI.ViewModels
{
    public class AddExpenseViewModel : ViewModelBase
    {
        IExpenseService  _expenseService;
        INavigationService _naviService;
        private int _userId;
        private ObservableCollection<ExpenseCategoryBindingModel> _categories;
        private DateTimeOffset _expenseTime;
        private ExpenseCategoryBindingModel _selectedCategory;
        private String _expenseComment;
        private string _language;
        
        private bool _isFlyoutOpen;

        private readonly RelayCommand _addExpenseCommand;

        private IReadOnlyDictionary<int, Icon> _icons;

        private async void DoAddExpense()
        {
            Expense expense = new Expense(_expenseTime.DateTime,Convert.ToInt32(_expenseAmount * 100) ,_userId,_selectedCategory.Id, _expenseComment);

            await _expenseService.InsertExpense(expense);

            this.SelectedCategory = null;
            this.Amount           = 0;
            this.IsFlyoutOpen     = false;
            this.Comment          = "";
            this.Time             = DateTime.Today;

            _naviService.NavigateTo("hub", typeof(HubPage));
        }

        
        public bool IsFlyoutOpen
        {
            get { return _isFlyoutOpen; }
            set { this.Set(() => IsFlyoutOpen, ref _isFlyoutOpen, value); }
        }


        private bool CanAddExpense()
        {
            return _expenseAmount > 0 && _selectedCategory != null;
        }

        public ICommand AddExpenseCommand
        {
            get { return _addExpenseCommand; }
        }

        public AddExpenseViewModel(IExpenseService expenseService,INavigationService navigationService, int UserId, string lang)
        {
            if (expenseService == null)
                throw new ArgumentNullException("expenseService");

            if (navigationService == null)
                throw new ArgumentNullException("navigationService");

            _expenseService = expenseService;
            _naviService    = navigationService;
            _userId = UserId;
            _addExpenseCommand = new RelayCommand(DoAddExpense, CanAddExpense);

            this.Amount           = 0.00m;
            this.Comment          = "";
            this.Time             = DateTime.Today;
            this.SelectedCategory = null;
            this._language = lang;
            this.Categories = new ObservableCollection<ExpenseCategoryBindingModel>();            
        }

        #region LoadData
        private bool loading = false;

        public async void LoadData()
        {
            if (loading)
                return;

            try
            {
                loading = true;

                if (_icons == null)
                {
                    _icons = await _expenseService.LoadCategoryIcons();
                }

                int? parentId = this.SelectedCategory == null ? (int?)null : this.SelectedCategory.Id;

                if (parentId.HasValue && parentId.Value == -1)
                    parentId = null;

                IEnumerable<ExpenseCategory> categories = await _expenseService.LoadCategories(parentId);

                if (categories.Count() > 0)
                {
                    ObservableCollection<ExpenseCategory> cats = new ObservableCollection<ExpenseCategory>(categories);

                    this.Categories.Clear();

                    if (parentId.HasValue)
                    {
                        //add fake "return" category
                        ExpenseCategory expenseCat = new ExpenseCategory("Return",18,"Return",null,-1);
                        this.Categories.Add(new ExpenseCategoryBindingModel(expenseCat, _icons[expenseCat.IconId.Value], this._language));

                        
                    }

                    foreach (ExpenseCategory ec in cats)
                        this.Categories.Add(new ExpenseCategoryBindingModel(ec, _icons[ec.IconId.Value], this._language));
                }
            }
            finally
            {
                loading = false;
            }
        }
        #endregion

        public ExpenseCategoryBindingModel SelectedCategory
        {
            get { return _selectedCategory; }
            set
            {
                Set<ExpenseCategoryBindingModel>(() => SelectedCategory, ref _selectedCategory, value);
                _addExpenseCommand.RaiseCanExecuteChanged();
                LoadData();
            }
        }

        public String SelectedCategoryName
        {
            get
            {
                return this.SelectedCategory == null ? "Not Selected" : this.SelectedCategory.Name;
            }
        }

        private Decimal _expenseAmount;

        public Decimal Amount
        {
            get { return _expenseAmount; }
            set
            {
                Set<Decimal>(()=>Amount,ref _expenseAmount,value);
                _addExpenseCommand.RaiseCanExecuteChanged();
            }
        }

        public String Comment
        {
            get { return _expenseComment; }
            set 
            { 
                Set<String>(() => Comment, ref _expenseComment, value); 
            }
        }


        public DateTimeOffset Time
        {
            get { return _expenseTime; }
            set
            {
                Set<DateTimeOffset>(() => Time, ref _expenseTime, value); 
            }
        }

        public ObservableCollection<ExpenseCategoryBindingModel> Categories
        {
            get 
            { 
                return _categories; 
            }
            set 
            { 
                Set<ObservableCollection<ExpenseCategoryBindingModel>>(()=>Categories,ref _categories,value); 
            }
        }

        public void SetLanguage(string lang)
        {
            _language = lang;
            this.LoadData();
        }
    }
}
